Hacking to try to get migrate to localhost going.
/* XXX create domain on CPU=-1 so that in future it auto load ballances by default */
if ( xc_domain_create( xc_handle, nr_pfns * (PAGE_SIZE / 1024),
- name, -1, &dom ) )
+ "", -1, &dom ) )
{
xcio_error(ioctxt, "Could not create domain. pfns=%d, %dKB",
nr_pfns,nr_pfns * (PAGE_SIZE / 1024));
"""
self.domain_by_id[info.id] = info
self.domain_db[info.id] = info.sxpr()
- self.domain_by_name[info.name] = info
+ for k, d in self.domain_by_name.items():
+ if k != d.name:
+ del self.domain_by_name[k]
+ if info.name:
+ self.domain_by_name[info.name] = info
self.sync_domain(info.id)
if notify: eserver.inject('xend.domain.created', [info.name, info.id])
@param id: domain id
@param notify: send a domain died event if true
"""
+ for info in self.domain_by_name.values():
+ if info.id == id:
+ del self.domain_by_name[info.name]
if id in self.domain_by_id:
info = self.domain_by_id[id]
- if notify: eserver.inject('xend.domain.died', [info.name, info.id])
- if info.name in self.domain_by_name:
- del self.domain_by_name[info.name]
del self.domain_by_id[id]
+ if notify: eserver.inject('xend.domain.died', [info.name, info.id])
if id in self.domain_db:
del self.domain_db[id]
self.db.delete(id)
"""
self.reap_cancel()
domlist = xc.domain_getinfo()
+ #for d in domlist:
+ # print 'reap> xen: ', d['dom'], d
+ #for d in self.domain_by_id.values():
+ # print 'reap> xend: ', d.id, d.info
casualties = []
for d in domlist:
dead = 0
log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason)
if reason in ['suspend']:
dominfo = self.domain_by_id.get(id)
- name = (dominfo and dominfo.name) or '??'
- eserver.inject('xend.domain.suspended', [name, id])
- continue
+ if dominfo.is_terminated():
+ log.debug('XendDomain>reap> Suspended domain died id=%s', id)
+ else:
+ name = (dominfo and dominfo.name) or '??'
+ eserver.inject('xend.domain.suspended', [name, id])
+ continue
if reason in ['poweroff', 'reboot']:
self.domain_restart_schedule(id, reason)
destroyed += 1
"""
self.refresh_cancel()
domlist = xc.domain_getinfo()
+ #for d in domlist:
+ # print 'refresh> xen: ', d['dom'], d
+ #for d in self.domain_by_id.values():
+ # print 'refresh> xend: ', d.id, d.info
# Index the domlist by id.
# Add entries for any domains we don't know about.
doms = {}
deferred.addCallback(cbok)
return deferred
+ def domain_setname(self, dom, name):
+ """Set the name of a domain.
+ For internal use only.
+
+ @param dom: domain id
+ @param name: domain name
+ """
+ return xc.domain_setname(dom=dom, name=name)
+
def domain_restart(self, dominfo):
"""Restart a domain.
deferred.addCallback(cbok)
return deferred
- def domain_configure(self, id, config):
+ def domain_configure(self, id, vmconfig):
"""Configure an existing domain. This is intended for internal
use by domain restore and migrate.
- @param id: domain id
- @param config: configuration
+ @param id: domain id
+ @param vmconfig: vm configuration
@return: deferred
"""
- print 'domain_configure>', id, config
+ print 'domain_configure>', id, vmconfig
+ config = sxp.child_value(vmconfig, 'config')
dominfo = self.domain_lookup(id)
print 'domain_configure>', 'dominfo=', dominfo
for dinfo in self.domain_by_id.values():
- print 'domain', dinfo.id, dinfo.name
- log.debug('domain_configure> id=%s config=%s', id, str(config))
+ print 'domain', 'id=', dinfo.id, 'name=', dinfo.name
+ log.debug('domain_configure> id=%s config=%s', str(id), str(config))
if dominfo.config:
- raise XendError("Domain already configured: " + dominfo.name)
+ raise XendError("Domain already configured: " + dominfo.id)
def cbok(dominfo):
self._add_domain(dominfo)
return dominfo
if not dominfo:
return
print 'check_name>', 'dom=', dominfo.name, dominfo.dom, 'self=', name, self.dom
+ if dominfo.is_terminated():
+ return
if not self.dom or (dominfo.dom != self.dom):
raise VmError('vm name clash: ' + name)
try:
self.name = sxp.child_value(config, 'name')
self.check_name(self.name)
+ if self.restore and self.dom:
+ xc.domain_setname(self.dom, self.name)
self.memory = int(sxp.child_value(config, 'memory'))
if self.memory is None:
raise VmError('missing memory size')
if self.restart_pending():
self.console.deregisterChannel()
else:
+ log.debug('Closing console, domain %s', self.id)
self.console.close()
chan = xend.getDomChannel(self.dom)
if chan:
self.xconsole = XendConsole.instance()
def op_configure(self, op, req):
+ """Configure an existing domain.
+ Configure is unusual in that it requires a domain id,
+ not a domain name.
+ """
fn = FormFn(self.xd.domain_configure,
- [['dom', 'str'],
+ [['dom', 'int'],
['config', 'sxpr']])
- deferred = fn(req.args, {'dom': self.dom.name})
+ deferred = fn(req.args, {'dom': self.dom.dom})
deferred.addErrback(self._op_configure_err, req)
return deferred
CURLFORM_COPYNAME, "op",
CURLFORM_COPYCONTENTS, "configure",
CURLFORM_END);
+ if(formcode){
+ eprintf("> Error adding op field.\n");
+ err = -EINVAL;
+ goto exit;
+ }
+ // POST the form.
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
+ err = curlresult(curl);
+ exit:
+ if(curl) curl_easy_cleanup(curl);
+ if(form) curl_formfree(form);
+ dprintf("< err=%d\n", err);
+ return err;
+}
+
+/** Get xend to unpause a domain.
+ *
+ * @param dom domain id
+ * @return 0 on success, error code otherwise
+ */
+int xen_domain_unpause(uint32_t dom){
+ int err = 0;
+ CURL *curl = NULL;
+ char url[128] = {};
+ int url_n = sizeof(url);
+ struct curl_httppost *form = NULL, *last = NULL;
+ CURLFORMcode formcode = 0;
+ dprintf("> dom=%u\n", dom);
+
+ err = curlsetup(&curl, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
+ if(err) goto exit;
+
+ // Op field.
+ formcode = curl_formadd(&form, &last,
+ CURLFORM_COPYNAME, "op",
+ CURLFORM_COPYCONTENTS, "unpause",
+ CURLFORM_END);
if(formcode){
eprintf("> Error adding op field.\n");
err = -EINVAL;
extern int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n);
+extern int xen_domain_unpause(uint32_t dom);
#endif
// Send xfr message and the domain state.
err = xfr_send_xfr(peer, state->vmid);
if(err) goto exit;
+ dprintf(">*** Sending domain %u\n", state->vmid);
err = xen_domain_snd(xend, peer->out,
state->vmid, state->vmconfig, state->vmconfig_n);
+ dprintf(">*** Sent domain %u\n", state->vmid);
if(err) goto exit;
// Sending the domain suspends it, and there's no way back.
// So destroy it now. If anything goes wrong now it's too late.
+ dprintf(">*** Destroying domain %u\n", state->vmid);
err = xfr_vm_destroy(xend, state->vmid);
if(err) goto exit;
+ err = xfr_error(peer, err);
+ if(err) goto exit;
IOStream_flush(peer->out);
// Read the response from the peer.
err = Conn_sxpr(peer, &sxpr);
int xfr_recv(Args *args, XfrState *state, Conn *peer){
int err = 0;
time_t t0 = time(NULL), t1;
+ Sxpr sxpr;
dprintf(">\n");
err = xen_domain_rcv(peer->in, &state->vmid_new, &state->vmconfig, &state->vmconfig_n);
if(err) goto exit;
-
+ // Read from the peer. This is just so we wait before configuring.
+ // When migrating to the same host the peer must destroy the domain
+ // before we configure the new one.
+ err = Conn_sxpr(peer, &sxpr);
+ if(err) goto exit;
+ sleep(2);
err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n);
if(err) goto exit;
-
+ err = xen_domain_unpause(state->vmid_new);
+ if(err) goto exit;
// Report new domain id to peer.
err = xfr_send_xfr_ok(peer, state->vmid_new);
if(err) goto exit;